package com.cheng.controller;

import com.alibaba.fastjson.JSONObject;
import com.cheng.service.FaceService.AuthService;
import com.cheng.service.FaceService.FaceService;
import com.cheng.service.FaceService.StudentService;
import com.cheng.utli.RedisUtil;
import com.cheng.utli.Utils;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

import static com.cheng.controller.Constant.*;

@Controller
@RequestMapping(value = "/Student")
public class StudentController {
    @Autowired
    private StudentService studentService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private FaceService faceService;


    private static final Logger logger = LoggerFactory.getLogger(StudentController.class);
    /**
     * 学生搜索cid
     * */
    @RequestMapping(value = "/searchCid" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject searchCid(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();
        //获得学生openid
        String openId = getSession(session);
        if(Utils.isBlank(openId)){
            return setReturnObjInfo("-100","没有登录");
        }
        //通过cid获得班级信息 1.查询redis缓存 2.查询
        String cid = request.getParameter("cid");
        //通过缓存获取
        JSONObject classInfo =JSONObject.parseObject((String) redisUtil.get(redisUtil.formatRedisKey(CLASS_KEY,cid)));
        if(!Utils.isNonBlank(classInfo)){
            classInfo = studentService.getClassInfo(openId,cid);
            if(!Utils.isNonBlank(classInfo)){
                return setReturnObjInfo("fail","请输入正确的班级编码");
            }
        }
        //判断是否已经添加该cid
        if(Utils.isNotBlank(classInfo.getString("hasAdd"))&&classInfo.getString("hasAdd").equals("yes")){
            return setReturnObjInfo("hasAdd","用户已经添加本班级");
        }
        //存入缓存将查询的信息
        returnObj.put("resCode","100");
        redisUtil.set(redisUtil.formatRedisKey(CLASS_KEY,cid),classInfo.toString(), 1000L);
        returnObj.put("info",classInfo);
        return returnObj;
    }

    /**
     * 学生加入班集体操作
     * */
    @RequestMapping(value = "/joinClass" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject joinClass(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();
        //获得学生openid
        String openId = getSession(session);
        //获得班级编码
        String cid = request.getParameter("cid");
        //判断cid是否存在
        JSONObject classInfo = studentService.getClassInfo(openId,cid);
        if(!Utils.isNonBlank(classInfo)){
            return setReturnObjInfo("fail","请输入正确的班级编码");
        }
        //判断是否已经添加该cid
        if(Utils.isNotBlank(classInfo.getString("hasAdd"))&&classInfo.getString("hasAdd").equals("yes")){
            return setReturnObjInfo("hasAdd","用户已经添加本班级");
        }

        //添加入表操作
        String result = studentService.joinClass(openId,cid);
        if(Utils.isBlank(result)){
            return setReturnObjInfo("fail","添加失败");
        }
        returnObj.put("resInfo","加入班级成功");
        returnObj.put("resCode",100);

        //删除缓存
        redisUtil.remove(redisUtil.formatRedisKey(CLASS_KEY,cid));
        redisUtil.remove(redisUtil.formatRedisKey(CLASSMEMBER,cid));
        return  returnObj;
    }


    public String getSession(HttpSession session){
        String openid = (String) session.getAttribute("openId");
        if(Utils.isNotBlank(openid)){
            return openid;
        }
        return null;
    }

    public static JSONObject setReturnObjInfo(String resCode, String resInfo) {
        JSONObject result = new JSONObject();
        result.put("resCode",resCode);
        result.put("resInfo",resInfo);
        return result;
    }




    /**
     * 进行签到功能
     * */
    @RequestMapping(value = "/SignIn" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject signIn(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();

        //获得签到类型  1.开启人脸签到 2.开启随机密码签到
        String type = request.getParameter("type");
        String cid = request.getParameter("cid");

        String openId = getSession(session);
        if(Utils.isBlank(openId)){
            return setReturnObjInfo("-100","没有登录");
        }

        if((type).contains("1,2")){
            return setReturnObjInfo("failParam","参数错误");
        }

        String key = redisUtil.formatRedisKey(CLASS_SIGN_KEY,cid);
        //查看过期时间
        if(!redisUtil.exists(key)){
            returnObj.put("resCode","noSignInTime");
            returnObj.put("resInfo","不在签到时间");
            return returnObj;
        }
        JSONObject result = studentService.getConductInfo(openId);
        String redisType =result.getString("type");
        if(!redisType.equals(type)){
            returnObj.put("resCode","typeError");
            returnObj.put("resInfo","签到类型不匹配");
            return returnObj;
        }
        if(type.equals("1")){
            //todo:获得用户拍照的照片
        }
        else{
            //获得学生输入的密码
            String password = request.getParameter("password");
            //获取缓存的密码
            String redisPassword = redisUtil.getString(redisUtil.formatRedisKey(CLASS_SIGN_KEY_PASSWORD,cid));

            if(!redisPassword.equals(password)){
                returnObj.put("resCode","passWordError");
                returnObj.put("resInfo","签到密码错误，请重新输入");
                return returnObj;
            }
            //修改签到状态  根据本次签到次数，学生openid进行修改
            studentService.updateSignInfo(openId,cid);
            //删除缓存
            redisUtil.remove(redisUtil.formatRedisKey(CLASS_SIGN_KEY,cid,openId));
            returnObj.put("resCode","100");
            return returnObj;
        }

        return returnObj;
    }

    /**
     * 签到页面实时刷新
     * */
    @RequestMapping(value = "/updateSignInPage" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject updateSignInPage(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();

        String cid = request.getParameter("cid");
        String type = request.getParameter("type");

        String key = redisUtil.formatRedisKey(CLASS_SIGN_KEY,cid,type);
        if(!redisUtil.exists(key)){
            returnObj.put("noSignInTime","不在签到时间");
            return returnObj;
        }
        //返回用户修改状态
        returnObj.put("info",studentService.getUserSignInfo(cid));

        return returnObj;
    }

    /**
     * 用户查询当前班级签到记录
     * */
    @RequestMapping(value = "/queryClassSignInInfo" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject queryClassSignInInfo(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();

        String openId = getSession(session);
        if(Utils.isBlank(openId)){
            return setReturnObjInfo("-100","没有登录");
        }

        String cid = request.getParameter("cid");

        String key = redisUtil.formatRedisKey(CLASS_SIGN_KEY,cid,openId);

        JSONObject userInfo = (JSONObject) redisUtil.getJson(key);


        if(userInfo == null){
            userInfo = studentService.queryClassSignInInfo(cid,openId);
            //得到的数据存入缓存
            redisUtil.set(key,userInfo.toString(), 600L);
        }
        returnObj.put("suc","100");
        returnObj.put("signInfo",userInfo);
        return returnObj;
    }

    /**
     * 查询用户的所有请假记录
     * */
    @RequestMapping(value = "/getUserAllLeaveInfo" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject getUserAllLeaveInfo(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();

        String openId = getSession(session);
        if(Utils.isBlank(openId)){
            return setReturnObjInfo("-100","没有登录");
        }
        String cid = request.getParameter("cid");
        redisUtil.remove(redisUtil.formatRedisKey(USER_GET_ALL_LEAVE_INFO,openId));
        String key = redisUtil.formatRedisKey(USER_GET_ALL_LEAVE_INFO,openId);

        JSONObject leaveList = redisUtil.getJson(key);

        if(leaveList ==null){
            leaveList = studentService.getUserAllLeaveInfo(openId,cid);
            redisUtil.set(key,leaveList.toString(),600L);
            logger.error("得到的leaveList的信息"+leaveList.toString());
        }
        returnObj.put("flag","no");
        for(int i=0; i<leaveList.getJSONArray("list").size();i++){
            JSONObject temp = leaveList.getJSONArray("list").getJSONObject(i);
            if(temp.getString("state").equals("0")){
                returnObj.put("flag","yes");
                break;
            }
        }
        returnObj.put("suc","100");
        returnObj.put("leaveList",leaveList);
        return  returnObj;
    }
    /**
     * 退出班级
     * */
    @RequestMapping(value = "/delClass" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject delClass(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();

        String openId = getSession(session);
        if(Utils.isBlank(openId)){
            return setReturnObjInfo("-100","没有登录");
        }
        String cid = request.getParameter("cid");
        studentService.delClass(openId,cid);
        return null;
    }
   /**
    *
    *
    * */
    /**
     * 用户请假操作
     * @param session
     * @param request
     * @return
     */
    @RequestMapping(value = "/userLeaveHandler" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject userLeaveHandler(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();

        String openId = getSession(session);
        if(Utils.isBlank(openId)){
            return setReturnObjInfo("-100","没有登录");
        }
        String leaveInfo =  request.getParameter("leaveInfo");
        //todo：得到上传的网络图片链接
        String leavePhoto = request.getParameter("leavePhoto");
        String cid = request.getParameter("cid");


        //进行请假操作
        HashMap map = new HashMap<String,String>();

        map.put("reason",leaveInfo);
        map.put("photo",leavePhoto);
        map.put("openId",openId);
        map.put("cid",cid);


        try {
            studentService.userLeaveHandler(map);
        } catch (Exception e) {
            returnObj.put("fail","-100");
            e.printStackTrace();
        }
        returnObj.put("rescode","100");

        return returnObj;
    }

    /**
     * 获得用户加入的班级
     * @param session
     * @param request
     * @return
     */
    @RequestMapping(value = "/getUserJoinClass" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject getUserJoinClass(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();

        String openId = getSession(session);
        if(Utils.isBlank(openId)){
            return setReturnObjInfo("-100","没有登录");
        }
        returnObj.put("classList", studentService.getUserJoinClass(openId));
        returnObj.put("suc","100");


        return returnObj;
    }


    @RequestMapping(value = "/getUserInfo" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject getUserInfo(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();

        String openId = getSession(session);
        if(Utils.isBlank(openId)){
            return setReturnObjInfo("-100","没有登录");
        }
        returnObj.put("info",studentService.getUserInfo(openId));

        returnObj.put("suc","100");
        return returnObj;
    }

    @RequestMapping(value = "/updateUserInfo" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject updateUserInfo(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();

        String openId = getSession(session);
        if(Utils.isBlank(openId)){
            return setReturnObjInfo("-100","没有登录");
        }
        //用户是否修改头像
        HashMap<String,String> userInfo = new HashMap<String,String>();
        userInfo.put("openId",openId);
        userInfo.put("name",request.getParameter("name"));
        String hasUrl= request.getParameter("hasUrl");
        if(hasUrl.equals(HAS)){
            String faceUrl = request.getParameter("faceUrl");
            userInfo.put("faceUrl",faceUrl);
            userInfo.put("user_id",request.getParameter("userId"));
            JSONObject result = faceService.matchFace(userInfo);
            logger.error(result.toString());
            if(result.getString("suc").equals("match")){
                userInfo.put("faceToken",result.getString("faceToken"));
                studentService.updateUserInfo(userInfo);

            }if(result.getString("suc").equals("noFace")){
                returnObj.put("noFace","没有检测到人脸信息，请重新上传");
                return returnObj;
            }
            if(result.getString("suc").equals("noMatch")){
                returnObj.put("noMatch","与注册不是同一人，请重新上传");
                return returnObj;
            }
        }
        else{
            studentService.updateUserInfo(userInfo);
        }
        returnObj.put("suc","100");
        return returnObj;
    }

    /**
     * 获取在进行的签到
     */
    @RequestMapping(value = "/getConductInfo" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject getConductInfo(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = null;

        String openId = getSession(session);
        if(Utils.isBlank(openId)){
            return setReturnObjInfo("-100","没有登录");
        }
        returnObj = studentService.getConductInfo(openId);
        if(returnObj==null){
            returnObj = new JSONObject();
            returnObj.put("noSignInfo","当前用户没有进行的签到");
            return returnObj;
        }
        long times = returnObj.getLongValue("time");
        Date date = new Date(times);
        //获取距离结束的时间
        returnObj.put("leftTime",getLeftTimeForNextDay(date));
        //获取签到者的经度和纬度
        Double latitudeFrom = Double.valueOf(request.getParameter("latitude"));
        Double longitudeFrom = Double.valueOf(request.getParameter("longitude"));

        JSONObject location = redisUtil.getJson(redisUtil.formatRedisKey(CLASSLOCATION,returnObj.getString("cid")));

        boolean flagDistance = getDistance(latitudeFrom,longitudeFrom,location.getDouble("latitude"),location.getDouble("longitude"));
        returnObj.put("flagDistance",flagDistance);
        return returnObj;
    }

    /**
     * test
     * */
    @RequestMapping(value = "/test" ,produces="text/html;charset=UTF-8")
    @ResponseBody
    public JSONObject test(HttpSession session, HttpServletRequest request){
        JSONObject returnObj = new JSONObject();

        studentService.Test();
        return returnObj;
    }

    /**
     * 计算二点之间的距离
     * @param longitudeFrom
     * @param latitudeFrom
     * @param longitudeTo
     * @param latitudeTo
     * @return
     */
    public static boolean getDistance(double longitudeFrom, double latitudeFrom, double longitudeTo, double latitudeTo) {
        GlobalCoordinates source = new GlobalCoordinates(latitudeFrom, longitudeFrom);
        GlobalCoordinates target = new GlobalCoordinates(latitudeTo, longitudeTo);

        return new GeodeticCalculator().calculateGeodeticCurve(Ellipsoid.Sphere, source, target).getEllipsoidalDistance()<30.00;
    }

    public static JSONObject getLeftTimeForNextDay(Date end){

        Date now = new Date();
        JSONObject result = new JSONObject();

        long date = end.getTime() - now.getTime();
        long day = date / (1000 * 60 * 60 * 24);
        long hour = (date / (1000 * 60 * 60) - day * 24);
        long min = ((date / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long second = (date/1000 - day*24*60*60 - hour*60*60 - min*60);
        if (day != 0){
            result.put("day", day);
        }
        if (hour < 10){
            result.put("hour1", 0);
            result.put("hour2", hour);
        } else {
            result.put("hour1", hour/10);
            result.put("hour2", hour%10);
        }
        if (min < 10){
            result.put("min1", 0);
            result.put("min2", min);
        } else {
            result.put("min1", min/10);
            result.put("min2", min%10);
        }
        if (second < 10){
            result.put("second1", 0);
            result.put("second2", second);
        } else {
            result.put("second1", second/10);
            result.put("second2", second%10);
        }

        return result;
    }
}
